package com.haozhang.lib;


import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.render.BlendMode;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.app.Context;

/**
 * @author HaoZhang
 */
public class SlantedTextView extends Component implements Component.DrawTask {

    public static final int MODE_LEFT = 0;
    public static final int MODE_RIGHT = 1;
    public static final int MODE_LEFT_BOTTOM = 2;
    public static final int MODE_RIGHT_BOTTOM = 3;
    public static final int MODE_LEFT_TRIANGLE = 4;
    public static final int MODE_RIGHT_TRIANGLE = 5;
    public static final int MODE_LEFT_BOTTOM_TRIANGLE = 6;
    public static final int MODE_RIGHT_BOTTOM_TRIANGLE = 7;

    public static final int ROTATE_ANGLE = 45;
    private Paint mPaint;
    private TextPaint mTextPaint;
    private float mSlantedLength = 40;
    private int mTextSize = 16;
    private int mSlantedBackgroundColor = Color.TRANSPARENT.getValue();
    private int mTextColor = Color.WHITE.getValue();
    private String mSlantedText = "";
    private int mMode = MODE_LEFT;
    private Context context;
    private static final String slantedTextSize = "slantedTextSize";
    private static final String slantedTextColor = "slantedTextColor";
    private static final String slantedLength = "slantedLength";
    private static final String slantedBackgroundColor = "slantedBackgroundColor";
    private static final String slantedText = "slantedText";
    private static final String slantedMode = "slantedMode";

    public SlantedTextView(Context context, AttrSet attrs) {
        this(context,attrs,null);

    }

    public SlantedTextView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
        addDrawTask(this);
    }


    public void init(AttrSet attrs) {

        boolean isPresentSlantedTextSize = attrs.getAttr(slantedTextSize).isPresent();
        if (isPresentSlantedTextSize) {
            mTextSize = attrs.getAttr(slantedTextSize).get().getDimensionValue();
        }
        boolean isPresenteslantedTextColor = attrs.getAttr(slantedTextColor).isPresent();
        if (isPresenteslantedTextColor) {
            mTextColor = attrs.getAttr(slantedTextColor).get().getColorValue().getValue();
        }
        boolean isPresentslantedLength = attrs.getAttr(slantedLength).isPresent();
        if (isPresentslantedLength) {
            mSlantedLength = attrs.getAttr(slantedLength).get().getDimensionValue();
        }
        boolean isPresentslantedBackgroundColor = attrs.getAttr(slantedBackgroundColor).isPresent();
        if (isPresentslantedBackgroundColor) {
            mSlantedBackgroundColor = attrs.getAttr(slantedBackgroundColor).get().getColorValue().getValue();
        }

        boolean isPresentslantedText = attrs.getAttr(slantedText).isPresent();
        if (isPresentslantedText) {
            mSlantedText = attrs.getAttr(slantedText).get().getStringValue();
        }
        boolean isPresentslantedMode = attrs.getAttr(slantedMode).isPresent();
        if (isPresentslantedMode) {
            String mModes = attrs.getAttr(slantedMode).get().getStringValue();
            if (mModes != null && !mModes.equals("")) {
                switch (mModes) {
                    case "left":
                        mMode = 0;
                        break;
                    case "right":
                        mMode = 1;
                        break;
                    case "left_bottom":
                        mMode = 2;
                        break;
                    case "right_bottom":
                        mMode = 3;
                        break;
                    case "left_triangle":
                        mMode = 4;
                        break;
                    case "right_triangle":
                        mMode = 5;
                        break;
                    case "left_bottom_triangle":
                        mMode = 6;
                        break;
                    case "right_bottom_triangle":
                        mMode = 7;
                        break;
                }
            }
        }

        LogUtil.error(this.getName(), "SlantedTextView --->" + mTextSize + "," + mTextColor + "," + mSlantedLength + "," + mSlantedBackgroundColor + "," + mSlantedText + "," + mMode);


        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mPaint.setAntiAlias(true);
        mPaint.setColor(new Color(mSlantedBackgroundColor));

        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(new Color(mTextColor));
    }



    private void drawBackground(Canvas canvas) {
        Path path = new Path();
        int w = getWidth();
        int h = getHeight();

        if (w != h) throw new IllegalStateException("SlantedTextView's width must equal to height");

        switch (mMode) {
            case MODE_LEFT:
                path = getModeLeftPath(path, w, h);
                break;
            case MODE_RIGHT:
                path = getModeRightPath(path, w, h);
                break;
            case MODE_LEFT_BOTTOM:
                path = getModeLeftBottomPath(path, w, h);
                break;
            case MODE_RIGHT_BOTTOM:
                path = getModeRightBottomPath(path, w, h);
                break;
            case MODE_LEFT_TRIANGLE:
                path = getModeLeftTrianglePath(path, w, h);
                break;
            case MODE_RIGHT_TRIANGLE:
                path = getModeRightTrianglePath(path, w, h);
                break;
            case MODE_LEFT_BOTTOM_TRIANGLE:
                path = getModeLeftBottomTrianglePath(path, w, h);
                break;
            case MODE_RIGHT_BOTTOM_TRIANGLE:
                path = getModeRightBottomTrianglePath(path, w, h);
                break;
        }
        path.close();
        canvas.drawPath(path, mPaint);
    }

    private Path getModeLeftPath(Path path, int w, int h) {
        path.moveTo(w, 0);
        path.lineTo(0, h);
        path.lineTo(0, h - mSlantedLength);
        path.lineTo(w - mSlantedLength, 0);
        return path;
    }

    private Path getModeRightPath(Path path, int w, int h) {
        path.lineTo(w, h);
        path.lineTo(w, h - mSlantedLength);
        path.lineTo(mSlantedLength, 0);
        return path;
    }

    private Path getModeLeftBottomPath(Path path, int w, int h) {
        path.lineTo(w, h);
        path.lineTo(w - mSlantedLength, h);
        path.lineTo(0, mSlantedLength);
        return path;
    }

    private Path getModeRightBottomPath(Path path, int w, int h) {
        path.moveTo(0, h);
        path.lineTo(mSlantedLength, h);
        path.lineTo(w, mSlantedLength);
        path.lineTo(w, 0);
        return path;
    }

    private Path getModeLeftTrianglePath(Path path, int w, int h) {
        path.lineTo(0,h);
        path.lineTo(w,0);
        return path;
    }

    private Path getModeRightTrianglePath(Path path, int w, int h) {
        path.lineTo(w,0);
        path.lineTo(w,h);
        return path;
    }

    private Path getModeLeftBottomTrianglePath(Path path, int w, int h) {
        path.lineTo(w,h);
        path.lineTo(0,h);
        return path;
    }

    private Path getModeRightBottomTrianglePath(Path path, int w, int h) {
        path.moveTo(0,h);
        path.lineTo(w,h);
        path.lineTo(w,0);
        return path;
    }

    private void drawText(Canvas canvas, int width, int height) {
        int w = (int) (width - mSlantedLength / 2);
        int h = (int) (height - mSlantedLength / 2);
        float[] xy = calculateXY(canvas, w, h);
        float toX = xy[0];
        float toY = xy[1];
        float centerX = xy[2];
        float centerY = xy[3];
        float angle = xy[4];

        canvas.rotate(angle, centerX, centerY);
        canvas.drawText(mTextPaint, mSlantedText, toX, toY);
    }

    private float[] calculateXY(Canvas canvas,int w, int h) {
        float[] xy = new float[5];
        Rect rect = null;
        RectF rectF = null;
        int offset = (int) (mSlantedLength / 2);
        switch (mMode) {
            case MODE_LEFT_TRIANGLE:
            case MODE_LEFT:
                rect = new Rect(0, 0, w, h);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(mSlantedText);
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.getWidth() - rectF.right) / 2.0f;
                rectF.top += (rect.getHeight() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2;
                xy[3] = h / 2;
                xy[4] = -ROTATE_ANGLE;
                break;
            case MODE_RIGHT_TRIANGLE:
            case MODE_RIGHT:
                rect = new Rect(offset, 0, w + offset, h);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(mSlantedText);
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.getWidth() - rectF.right) / 2.0f;
                rectF.top += (rect.getHeight() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2 + offset;
                xy[3] = h / 2;
                xy[4] = ROTATE_ANGLE;
                break;
            case MODE_LEFT_BOTTOM_TRIANGLE:
            case MODE_LEFT_BOTTOM:
                rect = new Rect(0, offset, w, h+offset);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(mSlantedText);
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.getWidth() - rectF.right) / 2.0f;
                rectF.top += (rect.getHeight() - rectF.bottom) / 2.0f;

                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2;
                xy[3] = h / 2 + offset;
                xy[4] = ROTATE_ANGLE;
                break;
            case MODE_RIGHT_BOTTOM_TRIANGLE:
            case MODE_RIGHT_BOTTOM:
                rect = new Rect(offset, offset, w+offset, h+offset);
                rectF = new RectF(rect);
                rectF.right = mTextPaint.measureText(mSlantedText);
                rectF.bottom = mTextPaint.descent() - mTextPaint.ascent();
                rectF.left += (rect.getWidth() - rectF.right) / 2.0f;
                rectF.top += (rect.getHeight() - rectF.bottom) / 2.0f;
                xy[0] = rectF.left;
                xy[1] = rectF.top - mTextPaint.ascent();
                xy[2] = w / 2 + offset;
                xy[3] = h / 2 + offset;
                xy[4] = -ROTATE_ANGLE;
                break;
        }
        return xy;
    }

    public SlantedTextView setText(String str) {
        mSlantedText = str;
        invalidate();
        return this;
    }


    public String getText() {
        return mSlantedText;
    }

    public SlantedTextView setSlantedBackgroundColor(int color) {
        mSlantedBackgroundColor = color;
        mPaint.setColor(new Color(mSlantedBackgroundColor));
        invalidate();
        return this;
    }

    public SlantedTextView setTextColor(int color) {
        mTextColor = color;
        mTextPaint.setColor(new Color(mTextColor));
        invalidate();
        return this;
    }


    public void setMode(int mode) {
        if (mMode > MODE_RIGHT_BOTTOM_TRIANGLE || mMode < 0)
            throw new IllegalArgumentException(mode + "is illegal argument ,please use right value");
        this.mMode = mode;
        invalidate();
    }

    public int getMode() {
        return mMode;
    }

    public SlantedTextView setTextSize(int size) {
        this.mTextSize = size;
        mTextPaint.setTextSize(mTextSize);
        invalidate();
        return this;
    }

    /**
     * set slanted space length
     *
     * @param length
     * @return this
     */
    public SlantedTextView setSlantedLength(int length) {
        mSlantedLength = length;
        invalidate();
        return this;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        drawBackground(canvas);
        drawText(canvas, component.getWidth(), component.getHeight());
    }
}
